﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using UricaoWeb.Datos.ConexionBD;
using UricaoWeb.LogicaDeNegocios.Cargos;
using UricaoWeb.Datos.Excepciones.Cargos;
using System.Data;
using System.Data.SqlClient;

namespace UricaoWeb.Datos.ConexionBD.Cargos
{
    public class AccesoDatos_Cargo
    {
        /// <summary>
        /// Clase que define la estructura de como la clase cargo accede a los datos existentes en la 
        /// base de datos.
        /// </summary>

        #region ParametrosDeLasFunciones

        //Instanciar la clase OperacionBD
        private OperacionesBD _bd;

        //Nombre de las funciones
        private readonly string _funcionVerificarExistencia = "verificarExistenciaCargo"; 
        private readonly string _funcionConsultarGeneral = "consultarCargosGeneral"; 
        private readonly string _funcionConsultarEstado = "consultarCargosPorEstado";
        private readonly string _funcionConsultarNombre = "consultarCargoPorNombre";
        private readonly string _funcionConsultarId = "consultarCargoPorId";
        private readonly string _funcionInsertar = "insertarCargo";
        private readonly string _funcionModificar = "modificarCargo";
        
        //Nombre de los parametros
        private readonly string _nombreCargo = "@nombre_Cargo";
        private readonly string _estadoCargo = "@estado_Cargo"; 
        private readonly string _idCargo = "@id_Cargo"; 
        private readonly string _nuevoNombreCargo = "@nuevo_nombre_Cargo"; 
        private readonly string _nuevoEstadoCargo = "@nuevo_estado_Cargo"; 

       
        //Nombre de los valores de retorno de las funciones
        private readonly string _valorRetornoNumerico = "@Return";
        private readonly string _Resultado = "Resultado";

        //Mensaje de las excepciones
        private readonly string _mensajeSQLExcepcion = "Conexion fallida a la base de datos del sistema";
        private readonly string _mensajeExcepcionGeneral = "Falla general del sistema";
        private readonly string _mensajeExcepcionNullObject = "Error al tratar de acceder a un objeto vacio";
        private readonly string _codigoErrorSQLExcepcion = "005";
        private readonly string _codigoErrorExcepcionGeneral = "006";
        private readonly string _codigoErrorExcepcionNullObject = "007";

        #endregion 
        
        #region ParametrosAccederTabla

        //Nombre de los campos en las tabla
        private readonly string _IdCampo = "IdCargo";
        private readonly string _NombreCampo = "nombreCargo";
        private readonly string _EstadoCampo = "activoCargo";
        
        #endregion

        #region Metodos

        /// <summary>
        /// Constructor de la clase
        /// </summary>
        public AccesoDatos_Cargo()
        {
            _bd = new OperacionesBD();
        }

        /// <summary>
        /// Metodo que crea un objeto de tipo de dato Cargo
        /// </summary>
        /// <param name="dr">Es un registro en donde estan contenido los valores de IdCargo, NombreCargo y EstadoCargo</param>
        /// <returns>Un Objeto de tipo Cargo</returns>
        public Cargo CrearCargo(DataRow dr)
        {
            Cargo _cargo = new Cargo();

            try
            {
                _cargo._id = int.Parse(dr[_IdCampo].ToString());
                _cargo._nombre = dr[_NombreCampo].ToString();
                _cargo._activo = bool.Parse(dr[_EstadoCampo].ToString());
                
            }
            catch (NullReferenceException e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionNullObject,_mensajeExcepcionNullObject, e);
            }
            catch (Exception e) 
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }
            return _cargo;
        }

        /// <summary>
        /// Metodo que crea un arreglo de objetos de tipo Cargo
        /// </summary>
        /// <param name="drc">Es un registro en donde estan contenido los valores de IdCargo, NombreCargo y EstadoCargo</param>
        /// <returns>Un arreglo de objetos de tipo Cargo</returns>
        public Cargo[] CrearArregloCargos(DataRowCollection drc)
        {
            Cargo[] _arregloCargo = null;
            try
            {
               _arregloCargo = new Cargo[drc.Count];
                int _iterador = 0;
                foreach (DataRow row in drc)
                {
                    _arregloCargo[_iterador] = CrearCargo(row);
                    _iterador++;
                }
                
            }
            catch (NullReferenceException e) 
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionNullObject, _mensajeExcepcionNullObject, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);

            }
            return _arregloCargo;
        }

        /// <summary>
        /// Metodo que me consulta los cargos de forma general es decir, no realiza la busqueda por ningun parametro
        /// en especifico.
        /// </summary>
        /// <returns>Un arreglo de objetos de tipo Cargo</returns>
        public Cargo[] ConsultarCargosGeneral()
        {
            Cargo[] _arregloCargo = null;
            try
            {
                SqlDataAdapter _datos = new SqlDataAdapter();
                _datos.SelectCommand = new SqlCommand(_funcionConsultarGeneral, _bd._cn);
                _datos.SelectCommand.CommandType = CommandType.StoredProcedure;
                DataSet dt = new DataSet();
                _datos.Fill(dt, _Resultado);

                _arregloCargo = CrearArregloCargos(dt.Tables[_Resultado].Rows);
            }
            catch (SqlException e) 
            {
                throw new CargoBDExcepcion(_codigoErrorSQLExcepcion, _mensajeSQLExcepcion, e);
            }
            catch (NullReferenceException e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionNullObject, _mensajeExcepcionNullObject, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }

            return _arregloCargo;
        
        }

        /// <summary>
        /// Metodo que realiza la busqueda de los cargos por un estado, bien sea activo o inactivo.
        /// </summary>
        /// <param name="estado">Si es true=activo y false=inactivo</param>
        /// <returns>Un arreglo de objetos de tipo Cargo</returns>
        public Cargo[] ConsultarCargosPorEstado(bool estado)
        {
            Cargo[] _arregloCargo = null;
            try
            {
                SqlDataAdapter _datos = new SqlDataAdapter();
                SqlCommand command = new SqlCommand(_funcionConsultarEstado, _bd._cn);
                command.Parameters.Add(new SqlParameter(_estadoCargo, SqlDbType.Bit)).Value = estado;
                _datos.SelectCommand = command;
                _datos.SelectCommand.CommandType = CommandType.StoredProcedure;

                DataSet dt = new DataSet();
                _datos.Fill(dt, _Resultado);

                _arregloCargo = CrearArregloCargos(dt.Tables[_Resultado].Rows);
            }
            catch (SqlException e) 
            {
                throw new CargoBDExcepcion(_codigoErrorSQLExcepcion, _mensajeSQLExcepcion, e);
            }
            catch (NullReferenceException e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionNullObject, _mensajeExcepcionNullObject, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }

            return _arregloCargo;
            
        }
       
        /// <summary>
        /// Metodo que realiza la busqueda de los cargos por el nombre del cargo.
        /// </summary>
        /// <param name="nombre">El nombre que deseo buscar</param>
        /// <returns>Un objeto del tipo Cargo</returns>
        public Cargo ConsultarCargoPorNombre(string nombre)
        {
            Cargo _cargo = null;
            try
            {
                SqlDataAdapter _datos = new SqlDataAdapter();
                SqlCommand command = new SqlCommand(_funcionConsultarNombre, _bd._cn);
                command.Parameters.Add(new SqlParameter(_nombreCargo, SqlDbType.NVarChar, new Cargo().getLongMaxNombre())).Value = nombre;
                _datos.SelectCommand = command;
                _datos.SelectCommand.CommandType = CommandType.StoredProcedure;

                DataSet dt = new DataSet();
                _datos.Fill(dt, _Resultado);

                _cargo = CrearCargo(dt.Tables[_Resultado].Rows[0]);
            }
            catch (SqlException e) 
            {
                throw new CargoBDExcepcion(_codigoErrorSQLExcepcion, _mensajeSQLExcepcion, e);
            }

            catch (NullReferenceException e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionNullObject, _mensajeExcepcionNullObject, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }

            return _cargo;
            
        }

        /// <summary>
        /// Metodo que verifica la existencia del cargo en la base de datos del sistema.
        /// </summary>
        /// <param name="nombre">El nombre del cargo introducido por el usuario</param>
        /// <returns>retorna 0 si el cargo esta disponible, en caso contrario retorma cualquier numero</returns>
        public int VerificarExistenciaCargo(string _NombreCargo)
        {
            int _coincidencia = -1;
            try
            {
                SqlCommand command = new SqlCommand(_funcionVerificarExistencia, _bd._cn);
                command.CommandType = System.Data.CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter(_nombreCargo, SqlDbType.NVarChar, new Cargo().getLongMaxNombre())).Value = _NombreCargo;
                command.Parameters.Add(_valorRetornoNumerico, SqlDbType.Int).Direction = ParameterDirection.ReturnValue;

                _bd._cn.Open();
                command.ExecuteNonQuery();
             
                _coincidencia = (int)(command.Parameters[_valorRetornoNumerico].Value);
            }
            catch (SqlException e)
            {
                throw new CargoBDExcepcion(_codigoErrorSQLExcepcion, _mensajeSQLExcepcion, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }
            finally
            {
                _bd._cn.Close();
            }

            return _coincidencia;
        }

        /// <summary>
        /// Metodo que modifica un cargo existente en la base de datos del sistema.
        /// </summary>
        /// <param name="nombre">El nombre del cargo introducido por el usuario</param>
        /// <param name="nuevoNombreCargo">El nuevo nombre del cargo que ha introducido el usuario</param>
        /// <param name="nuevoEstadoCargo">El estado que ha sido o no modificado por el usuario</param>
        /// <returns>retorna true si se pudo modificar el cargo, en caso contrario no se pudo modificar el mismo.</returns>

        public bool ModificarCargo(int idCargo, string nuevoNombreCargo, bool nuevoEstadoCargo)
        {
            bool _modifico = false;

            try
            {
                SqlCommand command = new SqlCommand(_funcionModificar, _bd._cn);
                command.CommandType = System.Data.CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter(_idCargo, SqlDbType.Int)).Value = idCargo;
                command.Parameters.Add(new SqlParameter(_nuevoNombreCargo, SqlDbType.NVarChar, new Cargo().getLongMaxNombre())).Value = nuevoNombreCargo;
                command.Parameters.Add(new SqlParameter(_nuevoEstadoCargo, SqlDbType.Bit)).Value = nuevoEstadoCargo;
                
                _bd._cn.Open();
                command.ExecuteNonQuery();

                _modifico = true;
            }
            catch (SqlException e)
            {
                throw new CargoBDExcepcion(_codigoErrorSQLExcepcion, _mensajeSQLExcepcion, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }
            finally
            {
                _bd._cn.Close();
            }
            return _modifico;
        }

        /// <summary>
        /// Metodo que inserta en la base de datos del sistema un nuevo registro (Cargo), por defecto
        /// todos los cargos que se esten creando sus estados seran activo.
        /// </summary>
        /// <param name="nombre">El nombre del cargo introducido por el usuario</param>
        /// <returns>retorna true si se pudo ingresar el cargo, en caso contrario no se pudo ingresar el mismo.</returns>

        public bool InsertarCargo(string _nombreC)
        {
            bool _inserto = false;
            try
            {
                SqlCommand command = new SqlCommand(_funcionInsertar, _bd._cn);
                command.CommandType = System.Data.CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter(_nombreCargo, SqlDbType.NVarChar, new Cargo().getLongMaxNombre())).Value = _nombreC;

                //_bd._cn.Open();
                command.ExecuteNonQuery();

                _inserto=true;
            }
            catch (SqlException e)
            {
                throw new CargoBDExcepcion(_codigoErrorSQLExcepcion, _mensajeSQLExcepcion, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }
            finally
            {
                _bd._cn.Close();
            }
            return _inserto;
        }
        /// <summary>
        /// Metodo que realiza la busqueda de los cargos por el identificador del mismo.
        /// </summary>
        /// <param name="id">El identificador del cargo a buscar</param>
        /// <returns>Un objeto del tipo Cargo</returns>
        public Cargo ConsultarCargoPorId(int id)
        {
            Cargo _cargo = null;

            try
            {
                SqlDataAdapter _datos = new SqlDataAdapter();
                SqlCommand command = new SqlCommand(_funcionConsultarId, _bd._cn);
                command.Parameters.Add(new SqlParameter(_idCargo, SqlDbType.Int)).Value = id;
                _datos.SelectCommand = command;
                _datos.SelectCommand.CommandType = CommandType.StoredProcedure;
                
                DataSet dt = new DataSet();
                _datos.Fill(dt, _Resultado);
                
                _cargo = CrearCargo(dt.Tables[_Resultado].Rows[0]);
            }
            catch (SqlException e)
            {
                throw new CargoBDExcepcion(_codigoErrorSQLExcepcion, _mensajeSQLExcepcion, e);
            }
            catch (NullReferenceException e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionNullObject, _mensajeExcepcionNullObject, e);
            }
            catch (Exception e)
            {
                throw new CargoBDExcepcion(_codigoErrorExcepcionGeneral, _mensajeExcepcionGeneral, e);
            }

            return _cargo;
           
        }


        #endregion 
    }
}